;;; init-search.el  -*- lexical-binding: t; -*-

;;
;; settings about ivy and company
;;
;; thanks for https://gist.github.com/takaxp/86158fe74b8268843571c42b48a4336c#file-init-ivy-el-L44
;;

;; Ivy
(use-package ivy
  :delight
  :hook (after-init . ivy-mode)
  :config
  (setq inhibit-compacting-font-caches t)

  (setq ivy-use-virtual-buffers t)
  (setq ivy-initial-inputs-alist nil)
  (setq enable-recursive-minibuffers t)
  (setq search-default-mode #'char-fold-to-regexp)

  ;; counsel-M-x, see also prescient.el section
  (setq ivy-initial-inputs-alist
        '(;; (org-refile . "^")
          (org-agenda-refile . "^")
          (org-capture-refile . "^")
          (counsel-describe-function . "^")
          (counsel-describe-variable . "^")
          ;; (counsel-org-capture . "^")
          (Man-completion-table . "^")
          (woman . "^")))

  (when (require 'smex nil t)
    (setq smex-history-length 35)
    (setq smex-completion-method 'ivy))

  ;;  https://github.com/abo-abo/swiper/issues/1294
  (defun ivy--sort-by-len (name candidates)
    "Sort CANDIDATES based on similarity of their length with NAME."
    (let ((name-len (length name))
          (candidates-count (length candidates)))
      (if (< 500 candidates-count)
          candidates
        (seq-sort-by #'length
                     (lambda (a b)
                       (< (abs (- name-len a))
                          (abs (- name-len b))))
                     candidates))))
  (setf (alist-get 'counsel-M-x ivy-sort-matches-functions-alist)
        #'ivy--sort-by-len)
  ;; (setf (alist-get 'counsel-M-x ivy-re-builders-alist)
  ;;           #'ivy--regex-ignore-order)  
  )

(use-package swiper
  :config
  (require 'counsel)
  (global-set-key (kbd "C-r") #'swiper)
  (global-set-key (kbd "C-s") #'counsel-grep-or-swiper)
  (global-set-key (kbd "C-c s") #'isearch-forward-regexp))

(use-package prescient
  :config
  ;;; ivy-prescient. コマンド履歴を保存．コマンドのイニシャル入力を可能にする．
  (when (require 'company-prescient nil t)
    (company-prescient-mode 1))

  (when (require 'prescient nil t)
    (setq prescient-aggressive-file-save t) ;; Merged!
    (setq prescient-save-file
          (expand-file-name "~/.emacs.d/prescient-save.el"))
    (prescient-persist-mode 1))

  (when (require 'ivy-prescient nil t)
    (setq ivy-prescient-retain-classic-highlighting t)
    ;; (dolist (command
    ;;          '(:not
    ;;            counsel-describe-variable
    ;;            counsel-describe-function
    ;;            counsel-M-x
    ;;            ))
    ;;   (add-to-list 'ivy-prescient-sort-commands command))
    (add-to-list 'ivy-re-builders-alist
                 '(counsel-M-x . ivy-prescient-re-builder))
    (setf (alist-get 'counsel-M-x ivy-re-builders-alist)
          #'ivy-prescient-re-builder)
    (ivy-prescient-mode 1)
    (setf (alist-get t ivy-re-builders-alist) #'ivy--regex-ignore-order))
  ;; ivy-re-builders-alist のデフォルトを奪い返す
  ;; この順で呼び出せば，counsel-M-x だけがフィルタの影響下に入る．
  ;;.ivy-prescient-re-builder の影響下にあると，イニシャル入力ができる．
  ;; e.g. M-x fap => find-file-at-point がヒット．
  )


(use-package counsel
  :delight
  :hook (ivy-mode . counsel-mode)
  :config
  (global-set-key (kbd "C-x C-r") #'counsel-recentf)
  (global-set-key (kbd "C-c C-r") 'ivy-resume))

(use-package ivy-rich
  :hook (counsel-mode . ivy-rich-mode))

;;; Shotcuts
(diminish 'which-key-mode)
(which-key-mode)

;;; Provide feature
(provide 'init-search)
